package Lambda;

import java.math.BigDecimal;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.function.Supplier;

public class LambdaInterface {

    //@FunctionalInterface注解
    //与 @Override 注解的作用类似，Java 8中专门为函数式接口引入了一个新的注解： @FunctionalInterface 。该注解可用于一个接口的定义上
    //通过JDK8源码javadoc，可以知道这个注解有以下特点：
    //1、该注解只能标记在"有且仅有一个抽象方法"的接口上。
    //2、JDK8接口中的静态方法和默认方法，都不算是抽象方法。
    //3、接口默认继承java.lang.Object，所以如果接口显示声明覆盖了Object中方法，那么也不算抽象方法。
    //4、该注解不是必须的，如果一个接口符合"函数式接口"定义，那么加不加该注解都没有影响。加上该注解能够更好地让	编译器进行检查。如果编写的不是函数式接口，但是加上了@FunctionInterface，那么编译器会报错。


    public void buildLambdaInterface(BigDecimal a){
        System.out.println("buildLambdaInterface Start");

        System.out.println(getSqu(()->a.add(a)));

        consumeString(
                s -> System.out.println(s.toUpperCase()),
                s -> System.out.println(s.toLowerCase()+",World"),
                "hello");

        predicates(s -> s.length() > 5);

        functions(s -> Integer.parseInt(s));

        System.out.println("buildLambdaInterface End");
    }


    //java.util.function.Supplier<T>接口仅包含一个无参的方法：T get()。
    // 用来获取一个泛型参数指定类型的对象数据。
    // 由于这是一个函数式接口，这也就意味着对应的Lambda表达式需要“对外提供”一个符合泛型类型的对象数据
    private BigDecimal getSqu(Supplier<BigDecimal> fun){
        BigDecimal a = fun.get().multiply(fun.get()) ;
        return a;
    }

    //java.util.function.Consumer<T>接口则正好与Supplier接口相反.
    // 它不是生产一个数据，而是消费一个数据，其数据类型由泛型决定。
    private static void consumeString(Consumer<String> one, Consumer<String> two, String s) {
        one.andThen(two).accept(s);
    }

    //有时候我们需要对某种类型的数据进行判断，从而得到一个boolean值结果。
    //这时可以使java.util.function.Predicate<T>接口。
    private static void predicates(Predicate<String> predicate) {
        boolean veryLong = predicate.test("HelloWorld");
        System.out.println("字符串很长吗：" + veryLong);
    }

    //java.util.function.Function<T,R>接口用来根据一个类型的数据得到另一个类型的数据.
    // 前者称为前置条件，后者称为后置条件。
    private static void functions(Function<String, Integer> function) {
        int num = function.apply("10");
        System.out.println(num);
    }

}
